package cn.south.campus.business.service.impl;

import cn.south.campus.business.mapper.PartTimeJobMapper;
import cn.south.campus.business.model.bo.LoginContext;
import cn.south.campus.business.model.entity.PartTimeJob;
import cn.south.campus.business.model.entity.PartTimeJobApply;
import cn.south.campus.business.model.enums.CampusErrorEnums;
import cn.south.campus.business.model.enums.PartTimeJobEnums;
import cn.south.campus.business.model.req.PartTimeJobReq;
import cn.south.campus.business.model.vo.PartTimeJobVo;
import cn.south.campus.business.service.PartTimeJobApplyService;
import cn.south.campus.business.service.PartTimeJobService;
import cn.south.campus.common.model.enums.CommonEnums;
import cn.south.campus.common.utils.AssertUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 校园兼职表 服务实现类
 * </p>
 *
 * @author chow
 * @since 2025-03-27
 */
@Service
@AllArgsConstructor
public class PartTimeJobServiceImpl extends ServiceImpl<PartTimeJobMapper, PartTimeJob> implements PartTimeJobService {

    private final PartTimeJobMapper partTimeJobMapper;

    private final PartTimeJobApplyService partTimeJobApplyService;

    @Override
    public IPage<PartTimeJobVo> pageQuery(PartTimeJobReq req) {
        LambdaQueryWrapper<PartTimeJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PartTimeJob::getStatus, PartTimeJobEnums.PartTimeJobStatus.PUBLISHED.getCode());
        PageDTO<PartTimeJob> timeJobPageDTO = partTimeJobMapper.selectPage(req.getPageDto(), wrapper);
        List<Long> timeJobIds = timeJobPageDTO.getRecords().stream().map(PartTimeJob::getId).collect(Collectors.toList());
        if (timeJobIds.isEmpty()) {
            return timeJobPageDTO.convert(PartTimeJobVo::convert);
        }
        Map<Long, Integer> idCntMap = partTimeJobApplyService.queryApplyCount(timeJobIds);
        return timeJobPageDTO.convert(item -> {
            PartTimeJobVo timeJobVo = PartTimeJobVo.convert(item);
            timeJobVo.setApplyCount(idCntMap.getOrDefault(item.getId(), 0));
            return timeJobVo;
        });
    }

    @Override
    public PartTimeJobVo queryById(Long id) {
        PartTimeJob partTimeJob = partTimeJobMapper.selectById(id);
        int checkApply = partTimeJobApplyService.checkApply(id);
        PartTimeJobVo timeJobVo = PartTimeJobVo.convert(partTimeJob);
        timeJobVo.setApplyStatus(checkApply);
        return timeJobVo;
    }

    @Override
    public void apply(Long id) {
        Long userId = LoginContext.getContext().getId();
        PartTimeJobVo partTimeJobVo = queryById(id);
        AssertUtils.isNotNull(partTimeJobVo, CommonEnums.DATA_HAS_NOT_ERROR);
        AssertUtils.isEquals(partTimeJobVo.getStatus(), PartTimeJobEnums.PartTimeJobStatus.PUBLISHED.getCode()
                , CampusErrorEnums.PART_TIME_JOB_STATUS_ERROR);
        int checkApply = partTimeJobApplyService.checkApply(id);
        AssertUtils.isEquals(checkApply, -1, CommonEnums.DATA_REPEAT_ERROR);
        PartTimeJobApply partTimeJobApply = new PartTimeJobApply();
        partTimeJobApply.setUserId(userId);
        partTimeJobApply.setJobId(id);
        partTimeJobApply.setStatus(PartTimeJobEnums.ApplyStatus.WAIT_AUDIT.getCode());
        partTimeJobApply.setApplyTime(LocalDateTime.now());
        partTimeJobApplyService.save(partTimeJobApply);
    }

    @Override
    public IPage<PartTimeJobVo> myApply(PartTimeJobReq req) {
        req.setUserId(LoginContext.getContext().getId());
        PageDTO<PartTimeJob> timeJobPageDTO = partTimeJobMapper.pageMyApply(req.getPageDto(), req);
        return timeJobPageDTO.convert(PartTimeJobVo::convert);
    }

    @Override
    public void cancelApply(Long id) {
        partTimeJobApplyService.cancelApply(id);
    }
}
